﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Security.Claims;
using TomNet.App.Model.DTO;
using TomNet.AspNetCore.Data;
using TomNet.AspNetCore.Mvc;
using TomNet.Authentication.JwtBearer;
using TomNet.Caching;
using TomNet.Core;
using TomNet.Core.Options;
using TomNet.Data;
using TomNet.Extensions;
using TomNet.Security;
using TomNet.SqlSugarCore.Entity;
using TomNet.Security.Claims;
using System.ComponentModel.DataAnnotations;

namespace TomNet.App.Web.Controllers.API
{
    public class DefaultController : ApiController
	{
		private readonly IUnitOfWork _unitOfWork;
		private IDistributedCache _cache;
		//private IHttpClientFactory _httpClientFactory;
		public DefaultController(IUnitOfWork unitOfWork, IServiceProvider provider)
		{
			_unitOfWork = unitOfWork;
			_cache = provider.GetService<IDistributedCache>();
			//_httpClientFactory = httpClientFactory;
		}

        #region AjaxResult Login(LoginParameter parameter) 登录。

        /// <summary>
        /// 登录。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost]
        public AjaxResult Login(LoginParameter parameter)
        {
            var login = _unitOfWork.DbContext.Queryable<Model.DB.Identity.UserLogin>().First(p => p.LoginName == parameter.LoginName && p.Password == parameter.LoginPass);
            if (login == null)
            {
                return new AjaxResult("账户或密码错误", AjaxResultType.Error);
            }

            var user = _unitOfWork.DbContext.Queryable<Model.DB.Identity.Users>().First(p => p.Id == login.UserID);
            var role = _unitOfWork.DbContext.Queryable<Model.DB.Identity.Role>().First(p => p.Id == user.RoleID);

            //生成Token，这里只包含最基本信息，其他信息从在线用户缓存中获取
            Claim[] claims =
            {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.UserName),
                new Claim(ClaimTypes.Role, user.RoleID + "," + role.Name),
                new Claim(ClaimTypes.MobilePhone,user.Phone),
                new Claim("LoginName", login.LoginName)
                //new Claim("UserInfo", TomNet.Json.JsonHelper.ToJson(user))
            };
            TomNetOptions options = HttpContext.RequestServices.GetTomNetOptions();
            string token = JwtHelper.CreateToken(claims, options);
            this.HttpContext.Response.Headers["Token"] = token;

            var result = new
            {
                UserName = user.UserName,
                LoginName = login.LoginName
            };
            return new AjaxResult("登录成功", AjaxResultType.Success, result);
        }

        public class LoginParameter
        {
            [Required()]
            public string LoginName { get; set; }

            [Required()]
            public string LoginPass { get; set; }
        }

        #endregion

        #region AjaxResult Register(RegisterParameter parameter) 注册。

        /// <summary>
        /// 注册。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost]
        public AjaxResult Register(RegisterParameter parameter)
        {
            var code = _cache.Get<string>("RegisterCode_" + parameter.Phone);
            if (code != parameter.Code)
            {
                return new AjaxResult("验证码错误", AjaxResultType.Error);
            }

            if (_unitOfWork.DbContext.Queryable<Model.DB.Identity.Users>().Any(p => p.UserName == parameter.UserName))
            {
                return new AjaxResult("用户名已存在", AjaxResultType.Error);
            }

            if (_unitOfWork.DbContext.Queryable<Model.DB.Identity.UserLogin>().Any(p => p.LoginName == parameter.Phone))
            {
                return new AjaxResult("登录名已存在", AjaxResultType.Error);
            }

            Model.DB.Identity.Users entityUser = new Model.DB.Identity.Users
            {
                Code = "",
                CreatedTime = DateTime.Now,
                Email = "",
                IdNumber = "",
                IsDeleted = false,
                Phone = parameter.Phone,
                ProportionID = 0,
                RoleID = 7,
                Sex = true,
                UserName = parameter.UserName,
                Token = ""
            };
            entityUser = _unitOfWork.DbContext.Insertable(entityUser).ExecuteReturnEntity();

            Model.DB.Identity.UserLogin entityLogin = new Model.DB.Identity.UserLogin
            {
                IsDeleted = false,
                LoginName = parameter.Phone,
                LoginType = 1,
                Password = parameter.LoginPass,
                UserID = entityUser.Id
            };
            _unitOfWork.DbContext.Insertable(entityLogin).ExecuteCommand();

            Model.DB.Identity.UserRoleMap entityRoleMap = new Model.DB.Identity.UserRoleMap
            {
                UserId = entityUser.Id,
                RoleId = 7
            };
            _unitOfWork.DbContext.Insertable(entityRoleMap).ExecuteCommand();

            return new AjaxResult("注册成功", AjaxResultType.Success);
        }

        public class RegisterParameter
        {
            [Required()]
            public string UserName { get; set; }

            [Required()]
            public string Phone { get; set; }

            [Required()]
            public string LoginPass { get; set; }

            [Required()]
            public string Code { get; set; }
        }

        #endregion

        #region AjaxResult RegisterCode(RegisterCodeParameter parameter) 注册验证码。

        /// <summary>
        /// 注册验证码。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost]
        public AjaxResult RegisterCode(RegisterCodeParameter parameter)
        {
            if (_unitOfWork.DbContext.Queryable<Model.DB.Identity.UserLogin>().Any(m => m.LoginName == parameter.Phone))
            {
                return new AjaxResult("用户名已存在", AjaxResultType.Error);
            }

            var check = _cache.Get<string>("PhoneMsgTime_" + parameter.Phone);
            if (check != null)
            {
                return new AjaxResult("请勿频繁获取手机验证码", AjaxResultType.Error);
            }

            Random random = new Random();
            var code = random.NextNumberString(5);

            //发送短信

            _cache.Set("PhoneMsgTime_" + parameter.Phone, code, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15) });
            _cache.Set("RegisterCode_" + parameter.Phone, code, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15) });
            return new AjaxResult("验证码已发送，测试 验证码：" + code, AjaxResultType.Success);
        }

        public class RegisterCodeParameter
        {
            public string Phone { get; set; }
        }

        #endregion

        #region AjaxResult FindPassword(FindPasswordParameter parameter) 找回密码。

        /// <summary>
        /// 找回密码。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost]
        public AjaxResult FindPassword(FindPasswordParameter parameter)
        {
            var validCode = _cache.Get<string>("FindPassWord_" + parameter.LoginName);
            if (validCode != parameter.Code)
            {
                return new AjaxResult("验证码错误", AjaxResultType.Error);
            }

            return new AjaxResult("验证成功", AjaxResultType.Success);
        }

        public class FindPasswordParameter
        {
            [Required()]
            public string LoginName { get; set; }

            [Required()]
            public string Code { get; set; }
        }

        #endregion

        #region AjaxResult FindPasswordCode(FindPasswordCodeParameter parameter) 找回密码验证码。

        /// <summary>
        /// 找回密码验证码。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost]
        public AjaxResult FindPasswordCode(FindPasswordCodeParameter parameter)
        {
            if (!_unitOfWork.DbContext.Queryable<Model.DB.Identity.UserLogin>().Any(m => m.LoginName == parameter.Phone))
            {
                return new AjaxResult("用户不存在", AjaxResultType.Error);
            }

            var check = _cache.Get<string>("PhoneMsgTime_" + parameter.Phone);
            if (check != null)
            {
                return new AjaxResult("请勿频繁获取手机验证码", AjaxResultType.Error);
            }

            Random random = new Random();
            var code = random.NextNumberString(5);

            //发送短信

            _cache.Set("PhoneMsgTime_" + parameter.Phone, code, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15) });
            _cache.Set("FindPassWord_" + parameter.Phone, code, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15) });
            return new AjaxResult("验证码已发送，测试 验证码：" + code, AjaxResultType.Success);
        }

        public class FindPasswordCodeParameter
        {
            [Required()]
            public string Phone { get; set; }
        }

        #endregion

        #region AjaxResult FindPasswordUpdate(FindPasswordUpdateParameter parameter) 找回密码的设置密码。

        /// <summary>
        /// 找回密码的设置密码。
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public AjaxResult FindPasswordUpdate(FindPasswordUpdateParameter parameter)
        {
            var userLogin = _unitOfWork.DbContext.Queryable<Model.DB.Identity.UserLogin>().Where(m => m.LoginName == parameter.LoginName).First();
            if (userLogin == null)
            {
                return new AjaxResult("用户不存在", AjaxResultType.Error);
            }
            userLogin.Password = parameter.LoginPass;//HashHelper.GetMd5(parameter.Password);

            _unitOfWork.DbContext.Updateable(userLogin).ExecuteCommand();

            return new AjaxResult("密码修改成功", AjaxResultType.Success);
        }

        public class FindPasswordUpdateParameter
        {
            [Required()]
            public string LoginName { get; set; }

            [Required()]
            public string LoginPass { get; set; }
        }

        #endregion
    }
}
